package Modellus.WinUI.ExampleTable;

import Modellus.Core.Model.Engine.Value;
import Modellus.Core.Model.IModel;
import Modellus.WinUI.Utils.ModellusColorPallete;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import java.awt.*;

public class BarCellRenderer extends DefaultTableCellRenderer implements TableCellRenderer {
    double _maximum = 0.0, _minimum = 0.0, _zeroPosition = 0.0, _value = 0.0;
    JTable _table;
    Color _color;
    private boolean _showBars = false;
    private IModel _model;
    Font _valueFont = new Font("Tahoma", Font.PLAIN, 10);

    public BarCellRenderer(IModel model) {
        _model = model;
        setOpaque(true);
        _color = ModellusColorPallete.BLUE;
    }

    public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) {
        _table = table;
        updateMaxAndMin(column);
        _value = (Double) _table.getValueAt(row, column);
        return this;
    }

    @Override
    public void paint(Graphics graphics) {
        Graphics2D graphics2D = (Graphics2D) graphics;
        if (_showBars) {
            graphics2D.setColor(_color);
            int start = (int) getFillStart();
            int end = (int) getFillWidth() - start;
            graphics2D.fillRoundRect(start + 2, 2, end, getHeight(), 2, 2);
        }
        graphics2D.setFont(_valueFont);
        graphics2D.setColor(Color.black);
        String value = Value.format(_value, _model.getDecimalPlaces(), _model.getExponentialThreshold());
        graphics2D.drawString(value, getWidth() - graphics2D.getFontMetrics().getStringBounds(value, graphics2D).getBounds().getSize().width, 12);
    }

    public void setColor(Color color) {
        _color = color;
    }

    private void updateMaxAndMin(int column) {
        int rows = _table.getModel().getRowCount();
        double currentValue;
        for (int row = 0; row < rows; row++) {
            currentValue = (Double) _table.getValueAt(row, column);
            if (Value.isBigger(currentValue, _maximum))
                _maximum = currentValue + 1.0;
            if (Value.isBigger(_minimum, currentValue))
                _minimum = currentValue - 1.0;
        }
        if (_maximum == _minimum)
            _zeroPosition = 0.0;
        else
            _zeroPosition = Math.abs(_minimum / (_maximum - _minimum));
    }

    private double getFillStart() {
        if (_value < 0)
            return getPosition(_value);
        else
            return _zeroPosition * getWidth();
    }

    private double getFillWidth() {
        if (_value < 0)
            return _zeroPosition * getWidth();
        else
            return getPosition(_value);
    }

    private double getPosition(double value) {
        return getWidthBetween(_minimum, value) * getWidthBetween(0, getWidth()) / getWidthBetween(_minimum, _maximum);
    }

    private double getWidthBetween(double minimum, double maximum) {
        return maximum - minimum;
    }

    public void setShowBars(boolean showBars) {
        _showBars = showBars;
    }
}